/*
 * Copyright (c) 2018.
 * http://www.ulabcare.com
 */

package com.mt.roll.upms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mt.roll.core.api.Assert;
import com.mt.roll.core.base.BaseService;
import com.mt.roll.core.dal.entity.SysOrg;
import com.mt.roll.core.dal.entity.SysUser;
import com.mt.roll.core.dal.service.SysOrgServiceBiz;
import com.mt.roll.core.dal.service.SysUserServiceBiz;
import com.mt.roll.core.errorcode.ApiErrorCode;
import com.mt.roll.core.params.EnabledParam;
import com.mt.roll.core.params.IdListParam;
import com.mt.roll.core.params.IdParam;
import com.mt.roll.core.utils.TreeUtil;
import com.mt.roll.core.vo.IdListVo;
import com.mt.roll.core.vo.IdVo;
import com.mt.roll.core.vo.PageVo;
import com.mt.roll.core.vo.R;
import com.mt.roll.upms.params.SysOrgParam;
import com.mt.roll.upms.params.SysOrgQueryParam;
import com.mt.roll.upms.service.OrgService;
import com.mt.roll.upms.vo.SysOrgVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 组织服务实现类
 * <p>
 * //TODO 需要完善区域限制，需要完善父组织修改功能
 * </p>
 *
 * @author jiff
 * @date 2018/11/9
 * @since 1.0
 */
@Service("upmsOrgService")
@Transactional
public class OrgServiceImpl extends BaseService implements OrgService {
    @Autowired
    private SysUserServiceBiz sysUserServiceBiz;
    @Autowired
    private SysOrgServiceBiz sysOrgServiceBiz;


    /**
     * 获取组织
     *
     * @param idParam 主键参数
     * @return 组织
     */
    @Override
    public R<SysOrgVo> get(IdParam idParam) {
        SysOrg sysOrg = sysOrgServiceBiz.getById(idParam.getId());
        Assert.notNull("组织不存在", sysOrg);

        if (!hasPermission(sysOrg)) {
            return failed(ApiErrorCode.FORBIDDEN_DATA);
        }
        SysOrgVo sysOrgVo = SysOrgVo.builder().build();
        BeanUtils.copyProperties(sysOrg, sysOrgVo);
        return successful(sysOrgVo);
    }


    /**
     * 获取组织列表
     *
     * @param sysOrgQueryParam 组织查询参数
     * @return 组织列表
     */
    @Override
    public R<List<SysOrgVo>> list(SysOrgQueryParam sysOrgQueryParam) {
        Long parentId = sysOrgQueryParam.getParentId();
        if (ObjectUtils.isNotNull(parentId) && !hasPermission(sysOrgServiceBiz.getById(parentId))) {
            return failed(ApiErrorCode.FORBIDDEN_DATA);
        }
        QueryWrapper<SysOrg> wrapper = new QueryWrapper<>();
        //没有指定父ID时则查询当前用户所能管理的所有组织，包括用户所在组织及所有子组织
        if (ObjectUtils.isNull(parentId)) {
            SysOrg parentOrg = sysOrgServiceBiz.getById(getLoginUser().getOrgId());
            wrapper.likeRight(SysOrg.GENEALOGY_ID, parentOrg.getGenealogyId());
        }
        wrapper.eq(ObjectUtils.isNotNull(parentId), SysOrg.PARENT_ID, parentId)
                .eq(ObjectUtils.isNotNull(sysOrgQueryParam.getEnabled()), SysOrg.ENABLED, sysOrgQueryParam.getEnabled())
                .like(StringUtils.isNotBlank(sysOrgQueryParam.getName()), SysOrg.NAME, sysOrgQueryParam.getName());
        List<SysOrg> sysOrgs = sysOrgServiceBiz.list(wrapper);
        List<SysOrgVo> sysOrgVos = com.mt.roll.core.utils.BeanUtils.copyList(sysOrgs, SysOrgVo.class);
        return successful(sysOrgVos);
    }

    /**
     * 获取组织分页列表
     *
     * @param sysOrgQueryParam 组织查询参数
     * @return 组织分页列表
     */
    @Override
    public R<PageVo<SysOrgVo>> page(SysOrgQueryParam sysOrgQueryParam) {
        Long parentId = sysOrgQueryParam.getParentId();
        if (ObjectUtils.isNotNull(parentId) && !hasPermission(sysOrgServiceBiz.getById(parentId))) {
            return failed(ApiErrorCode.FORBIDDEN_DATA);
        }
        QueryWrapper<SysOrg> wrapper = new QueryWrapper<>();
        //没有指定父ID时则查询当前用户所能管理的所有组织，包括用户所在组织及所有子组织
        if (ObjectUtils.isNull(parentId)) {
            SysOrg parentOrg = sysOrgServiceBiz.getById(getLoginUser().getOrgId());
            wrapper.likeRight(SysOrg.GENEALOGY_ID, parentOrg.getGenealogyId());
        }
        wrapper.eq(ObjectUtils.isNotNull(parentId), SysOrg.PARENT_ID, parentId)
                .eq(ObjectUtils.isNotNull(sysOrgQueryParam.getEnabled()), SysOrg.ENABLED, sysOrgQueryParam.getEnabled())
                .like(StringUtils.isNotBlank(sysOrgQueryParam.getName()), SysOrg.NAME, sysOrgQueryParam.getName());
        IPage<SysOrg> page = sysOrgServiceBiz.page(new Page<>(sysOrgQueryParam.getCurrent(), sysOrgQueryParam.getSize()), wrapper);
        return successful(new PageVo<>(page, SysOrgVo.class));
    }

    /**
     * 获取组织树列表
     *
     * @param sysOrgQueryParam 组织查询参数
     * @return 组织树列表
     */
    @Override
    public R<List<SysOrgVo>> tree(SysOrgQueryParam sysOrgQueryParam) {
        Long parentId = sysOrgQueryParam.getParentId();
        SysOrg parentOrg = null;
        if (ObjectUtils.isNotNull(parentId)) {
            parentOrg = sysOrgServiceBiz.getById(parentId);
            if (!hasPermission(sysOrgServiceBiz.getById(parentId))) {
                return failed(ApiErrorCode.FORBIDDEN_DATA);
            }
        }
        QueryWrapper<SysOrg> wrapper = new QueryWrapper<>();
        //没有指定父ID时则查询当前用户所能管理的所有组织，包括用户所在组织及所有子组织
        if (ObjectUtils.isNull(parentId)) {
            parentOrg = sysOrgServiceBiz.getById(getLoginUser().getOrgId());
            wrapper.likeRight(SysOrg.GENEALOGY_ID, parentOrg.getGenealogyId());
        }
        wrapper.eq(ObjectUtils.isNotNull(parentId), SysOrg.PARENT_ID, parentId)
                .eq(ObjectUtils.isNotNull(sysOrgQueryParam.getEnabled()), SysOrg.ENABLED, sysOrgQueryParam.getEnabled())
                .like(StringUtils.isNotBlank(sysOrgQueryParam.getName()), SysOrg.NAME, sysOrgQueryParam.getName());
        List<SysOrg> sysOrgs = sysOrgServiceBiz.list(wrapper);
        List<SysOrgVo> sysOrgVos = com.mt.roll.core.utils.BeanUtils.copyList(sysOrgs, SysOrgVo.class);
        return successful(TreeUtil.toTree(sysOrgVos, parentOrg.getParentId()));
    }

    /**
     * 新增组织
     *
     * @param sysOrgParam 组织参数
     * @return 主键
     */
    @Override
    public R<IdVo> add(SysOrgParam sysOrgParam) {
        SysOrg parentOrg = sysOrgServiceBiz.getById(sysOrgParam.getParentId());
        if (parentOrg == null) {
            return failed("父组织不存在");
        }
        if (!hasPermission(parentOrg)) {
            return failed(ApiErrorCode.FORBIDDEN_DATA);
        }

        SysOrg sysOrg = new SysOrg();
        BeanUtils.copyProperties(sysOrgParam, sysOrg);
        //数据库不允许为空，先设置父组织的家谱ID
        sysOrg.setGenealogyId(parentOrg.getGenealogyId());
        setCommonField(sysOrg);
        sysOrgServiceBiz.save(sysOrg);
        //设置家谱ID，格式：/rootId/.../grandfatherId/parentId/id
        sysOrg.setGenealogyId(parentOrg.getGenealogyId() + "/" + sysOrg.getId());
        sysOrgServiceBiz.updateById(sysOrg);
        return successful(IdVo.builder().id(sysOrg.getId()).build());
    }

    /**
     * 更新组织
     *
     * @param sysOrgParam 组织参数
     * @return 主键
     */
    @Override
    public R<IdVo> update(SysOrgParam sysOrgParam) {
        SysOrg sysOrg = sysOrgServiceBiz.getById(sysOrgParam.getId());
        Assert.notNull("组织不存在", sysOrg);
        if (!hasPermission(sysOrg)) {
            return failed(ApiErrorCode.FORBIDDEN_DATA);
        }
        //父组织关系暂时不允许修改，先不验证
//        SysOrg parentOrg = sysOrgService.getById(sysOrgParam.getParentId());
//        Assert.notNull("父组织不存在", parentOrg);
//        if (!hasPermission(parentOrg)) {
//            return failed(ApiErrorCode.FORBIDDEN_DATA);
//        }


        SysOrg updateSysOrg = new SysOrg();
        BeanUtils.copyProperties(sysOrgParam, updateSysOrg, "parentId");
        setUpdateCommonField(updateSysOrg);
        sysOrgServiceBiz.updateById(updateSysOrg);
        return successful(IdVo.builder().id(sysOrg.getId()).build());
    }

    /**
     * 启用停用
     *
     * @param enabledParam 启停参数
     * @return 主键
     */
    @Override
    public R<IdVo> enabled(EnabledParam enabledParam) {
        SysOrg sysOrg = sysOrgServiceBiz.getById(enabledParam.getId());
        if (sysOrg == null) {
            return failed("组织不存在");
        }
        if (!hasPermission(sysOrg)) {
            return failed(ApiErrorCode.FORBIDDEN_DATA);
        }
        if (!enabledParam.getEnabled().equals(sysOrg.getEnabled())) {
            SysOrg updateSysOrg = new SysOrg().setId(sysOrg.getId());
            updateSysOrg.setEnabled(enabledParam.getEnabled());
            setUpdateCommonField(updateSysOrg);
            sysOrgServiceBiz.updateById(updateSysOrg);
        }
        return successful(IdVo.builder().id(sysOrg.getId()).build());
    }

    /**
     * 删除组织
     *
     * @param idParam 主键参数
     * @return 主键
     */
    @Override
    public R<IdVo> delete(IdParam idParam) {
        SysOrg sysOrg = sysOrgServiceBiz.getById(idParam.getId());
        if (sysOrg == null) {
            return failed("组织不存在");
        }
        if (sysUserServiceBiz.count(new QueryWrapper<SysUser>().eq(SysUser.ORG_ID, sysOrg.getId())) > 0) {
            return failed("该组织下还有用户");
        }
        //用家谱ID查询会包含当前要删除的组织，所以需要判断大于1时则还有子组织
        if (sysOrgServiceBiz.count(new QueryWrapper<SysOrg>().likeRight(SysOrg.GENEALOGY_ID, sysOrg.getGenealogyId())) > 1) {
            return failed("该组织下还有子组织");
        }
        sysOrgServiceBiz.removeById(idParam.getId());
        return successful(IdVo.builder().id(sysOrg.getId()).build());
    }

    /**
     * 批量删除组织
     *
     * @param idListParam 主键列表参数
     * @return 主键列表
     */
    @Override
    public R<IdListVo> delete(IdListParam idListParam) {
        return null;
    }


    /**
     * 判断登录用户是否有修改该组织的权限，主要基于登录用户和被修改组织是否归属同一组织或上下级组织关系
     *
     * @param sysOrg 被修改的用户
     * @return true允许修改，否则不允许
     */
    private boolean hasPermission(SysOrg sysOrg) {
        if (sysOrg == null) {
            return false;
        }
        Long loginOrgId = getLoginUser().getOrgId();
        if (loginOrgId == null) {
            return false;
        }
        SysOrg loginSysOrg = sysOrgServiceBiz.getById(loginOrgId);
        if (loginSysOrg == null) {
            return false;
        }
        if (StringUtils.isAnyBlank(sysOrg.getGenealogyId(), loginSysOrg.getGenealogyId())) {
            return false;
        }
        return sysOrg.getGenealogyId().startsWith(loginSysOrg.getGenealogyId());
    }
}
